#include "../Server.hpp"
#include <iostream>
#include <string.h>

void handle_write(Channel *pc,Socket *s,void *data)
{
    s->Send(data,strlen((char *)data));
    delete[] data;
    pc->CancelWriteMonitor();
    pc->SetCurrentEvents(EPOLLIN | EPOLLRDHUP);
}

void handle_read(Channel *pc,Socket *s)
{
    char *buffer = new char[1024]{0};
    int n = s->Recv(buffer,sizeof(buffer)-1);
    if(n > 0)
    {
        buffer[n] = 0;
        std::cout << "接收到消息: " << buffer << std::endl;
    }
    pc->CancelReadMonitor();
    pc->SetCurrentEvents(EPOLLOUT | EPOLLRDHUP);
    pc->SetWriteCallBack(std::bind(handle_write,pc,s,buffer));
}

void handle_broken(Channel *pc,Socket *s)
{
    pc->CancelAllMonitor();
    s->Close();
    std::cout << s->GetFd() << "号连接断开！" << std::endl;
    delete pc;
    delete s;
}

void handle_any(EventLoop *pl,uint32_t timerid)
{
    pl->TimerRefresh(timerid);
    std::cout << "handle_any" << std::endl;
}

void hendle_accept(EventLoop *pl,Channel *pc,Socket *s)
{
    int connfd = s->Accept();
    std::cout << "获取到新连接: " << connfd << std::endl;
    Socket *conn = new Socket(connfd);// 接收到连接，创建一个套接字

    pl->AddTimer(1,std::bind(handle_broken,pc,conn),5);// 添加一个定时事件

    // 创建Channel对象，并设置好监听事件和回调函数
    Channel *conn_ch = new Channel(pl,conn->GetFd());
    conn_ch->SetReadCallBack(std::bind(handle_read,conn_ch,conn));
    conn_ch->SetAnyCallBack(std::bind(handle_any,pl,1));
    conn_ch->SetBrokenCallBack(std::bind(handle_broken,conn_ch,conn));
    conn_ch->SetCurrentEvents(EPOLLIN | EPOLLRDHUP);
}

int main()
{
    Socket *listen = new Socket();// 创建监听套接字
    listen->Create(true);// true->启动地址重用
    listen->Bind(9090);
    listen->Listen();// 启动监听
    
    EventLoop *pl = new EventLoop();// Poller对象:负责监听
    Channel *listen_ch = new Channel(pl,listen->GetFd());// 为监听套接字创建Channel对象，方便Poller管理
    listen_ch->SetReadCallBack(std::bind(hendle_accept,pl,listen_ch,listen));// 设置可读事件触发后的回调(实际上就是接收连接套接字)
    listen_ch->SetCurrentEvents(EPOLLIN);

    pl->Start();// 该函数会将触发的Channel对象放入vector中

    listen->Close();
    delete listen;
    return 0;
}